package com.darwin.darwinIsometric.map
{
	import com.darwin.darwinIsometric.core.IsoObject;
	import com.darwin.darwinIsometric.core.IsoPosition;
	import com.darwin.darwinIsometric.core.isoConst.IsoType;
	import com.darwin.darwinIsometric.pathfinding.MapGrid;
	import com.darwin.darwinNameSpace.darwin;
	
	import flash.utils.Dictionary;
	import flash.utils.getTimer;

	/**
	 * isoMap保存整个IsoWorld中的地图信息
	 * @author lipi
	 */
	public class IsoMap
	{
		public function IsoMap()
		{
			_dic = new Dictionary();
			_floorDic = new Dictionary();
			_changeObjectDic = new Dictionary();
			
			_isoPositionDic = new Dictionary();
			_maxIsoPositionDic = new Dictionary();
			
			_walkableChangeList = [];
		}
		
		//保存对象的位置，以方便之后对象位置改变时的处理
		private var _isoPositionDic:Dictionary;
		private var _maxIsoPositionDic:Dictionary;
		
		
		/**
		 * 保存isoObject对象
		 */
		private var _dic:Dictionary;
		
		/**
		 * 保存地板的isoObject对象
		 */
		private var _floorDic:Dictionary;
		
		/**
		 * 已经变化的物件列表
		 */
		private var _changeObjectDic:Dictionary;
		
		/**
		 *	已变化的物件的数量 
		 */
		private var _changeObjectCount:int;
		
		/**
		 * 可行走状态被改变列表
		 */
		private var _walkableChangeList:Array;
		
		
		/**
		 * 取得isoObject列表
		 */
		public function getIsoList():Vector.<IsoObject>
		{
			var $vector:Vector.<IsoObject> = new Vector.<IsoObject>();
			for(var item:Object in _isoPositionDic)
			{
				$vector.push(item as IsoObject);
			}
			return $vector;
		}
		
		
		/**
		 * 重置地图对象
		 */
		public function reset():void
		{
			_dic = new Dictionary();
			_floorDic = new Dictionary();
			_changeObjectDic = new Dictionary();
			_isoPositionDic = new Dictionary();
			_maxIsoPositionDic = new Dictionary();
			_mapGrid = null;
			_walkableChangeList = [];
			_changeObjectCount = 0;
		}
		
		public var minX:Number = 0;
		
		public var minZ:Number = 0;
		
		public var maxX:Number = 0;
		
		public var maxZ:Number = 0;
		
		
		/**
		 * 添加一个IsoObject对象到地图数据中
		 * @param iso
		 */
		public function addIsoObject(isoObject:IsoObject):void
		{
			addChangeObjectToMap();
			exeAddIsoObject(isoObject);
		}
		
		private function exeAddIsoObject(isoObject:IsoObject):void
		{
			var $p:IsoPosition = isoObject.isoPosition;
			var $mp:IsoPosition = isoObject.maxIsoPosition;
			
			_isoPositionDic[isoObject] = $p;//记录被添加时的位置
			_maxIsoPositionDic[isoObject] = $mp;//记录被添加时的位置
			
			
			if($p.x < minX) minX = $p.x;
			if($p.z < minZ) minZ = $p.z;
			if($mp.x > maxX) maxX = $mp.x;
			if($mp.z > maxZ) maxZ = $mp.z;
			
			var isoMapItem:IsoMapItem;
			if($p.x == $mp.x && $p.z == $mp.z)
			{
				isoMapItem = getMapItem($p.x,$p.z,isoObject.isoType,false);
				if(isoMapItem == null) isoMapItem = createMapItem($p.x,$p.z,isoObject.isoType);
				isoMapItem.addIsoObject(isoObject);
				if(isoObject.simple == false && _mapGrid && _walkableChangeList.length <= 1000) _walkableChangeList.push([$p.x,$p.z]);//walkable改变列表,1000为防止场景中不断改变位置的物体
			}else{
				for(var x1:int = $p.x,x2:int = $mp.x; x1 <= x2; x1++)
				{
					for(var z1:int = $p.z,z2:int = $mp.z; z1<=z2; z1++)
					{
						isoMapItem = getMapItem(x1,z1,isoObject.isoType,false);
						if(isoMapItem == null) isoMapItem = createMapItem(x1,z1,isoObject.isoType);
						isoMapItem.addIsoObject(isoObject);
						if(isoObject.simple == false && _mapGrid && _walkableChangeList.length <= 1000) _walkableChangeList.push([x1,z1]);//walkable改变列表,1000为防止场景中不断改变位置的物体
					}//for
				}//for
			}//if
		}
		
		
		/**
		 * 从地图数据中删除一个IsoObject对象
		 * oldPosition 表示是否从旧位置移除对象
		 * @param iso
		 */
		public function removeIsoObject(isoObject:IsoObject):void
		{
			addChangeObjectToMap();
			exeRemoveIsoObject(isoObject);
		}
		
		//执行实际的remove相关操作
		private function exeRemoveIsoObject(isoObject:IsoObject):void
		{
			var $p:IsoPosition = _isoPositionDic[isoObject];
			var $mp:IsoPosition = _maxIsoPositionDic[isoObject];
			delete _isoPositionDic[isoObject];
			delete _maxIsoPositionDic[isoObject];
			delete _changeObjectDic[isoObject];
			_changeObjectCount--;
			
			var isoMapItem:IsoMapItem;
			if($p.x == $mp.x && $p.z == $mp.z)
			{
				isoMapItem = getMapItem($p.x,$p.z,isoObject.isoType,false);
				if(isoMapItem != null) isoMapItem.removeIsoObject(isoObject);
				if(isoObject.simple == false && _mapGrid && _walkableChangeList.length <= 1000) _walkableChangeList.push([$p.x,$p.z]);//walkable改变列表,1000为防止场景中不断改变位置的物体
			}else{
				for(var x1:int = $p.x,x2:int = $mp.x; x1 <= x2; x1++)
				{
					for(var z1:int = $p.z,z2:int = $mp.z; z1<=z2; z1++)
					{
						isoMapItem = getMapItem(x1,z1,isoObject.isoType,false);
						if(isoMapItem != null) isoMapItem.removeIsoObject(isoObject);
						if(isoObject.simple == false &&  _mapGrid && _walkableChangeList.length <= 1000) _walkableChangeList.push([x1,z1]);//walkable改变列表,1000为防止场景中不断改变位置的物体
					}//for
				}//for
			}
		}
		
		
		
		/**
		 * 将状态被改变的对象做上标记存到字典
		 */
		public function addChangeIsoObject(isoObject:IsoObject):IsoObject
		{
			if(_isoPositionDic[isoObject]  == null || _maxIsoPositionDic[isoObject] == null)
			{
				return null;
			}else{
				if(_changeObjectDic[isoObject] == null)_changeObjectCount++;
				_changeObjectDic[isoObject] = isoObject;
				return isoObject;
			}
		}
		
		
		/**
		 * 通过一个坐标点取得物件列表
		 */
		public function getObjectListByXZ(x:int,z:int,type:String = IsoType.OBJECT):Array
		{
			var $isoMapItem:IsoMapItem = getMapItem(x,z,type);
			if($isoMapItem == null) return [];
			var $listDic:Dictionary = $isoMapItem.objectDic;
			
			var $returnArr:Array = [];
			var item:Object;
			for each(item in $listDic)
			{
				$returnArr.push(item);
			}
			return $returnArr;
		}
		
		
		/**
		 * 通过一个范围取得所有物件列表
		 */
		public function getObjectListByRange(startX:int,startZ:int,endX:int,endZ:int,type:String = IsoType.OBJECT):Array
		{
			var $returnArr:Array = [];
			var item:Object;
			for(var x1:int = startX;x1<=endX;x1++)
			{
				for(var z1:int = startZ;z1<=endZ;z1++)
				{
					var $isoMapItem:IsoMapItem = getMapItem(x1,z1,type);
					if($isoMapItem != null)
					{
						var $listDic:Dictionary = $isoMapItem.objectDic;
						for each(item in $listDic)
						{
								$returnArr.push(item);
						}
					}
				}
			}
			return $returnArr;
		}
		
		private var _mapGrid:MapGrid;
		
		/**
		 * 取得当前地图的供寻路数组
		 */
		public function getMapGrid(cols:int,rows:int,startX:int = 0,startY:int = 0):MapGrid
		{
			if(_mapGrid == null || 
				_mapGrid.startX != startX || _mapGrid.startY != startY ||
				_mapGrid.numCols != cols || _mapGrid.numRows != rows || _walkableChangeList.length > 1000)
			{
				_mapGrid = new MapGrid(cols,rows,startX,startY);
				for(var sx:int = 0;sx<cols;sx++)
				{
					for(var sy:int = 0;sy<rows;sy++)
					{
						_mapGrid.setWalkable(sx,sy,getWalkable(sx+startX,sy+startY));
					}
				}
				_walkableChangeList.length = 0;//清除改变列表
			}else{
				pushWalkableList();
				_walkableChangeList.length = 0;//清除改变列表
			}
			
			return _mapGrid;
		}
		
		//添加改变的状态列表 
		private function pushWalkableList():void
		{
			addChangeObjectToMap();
			for(var i:int = 0;i<_walkableChangeList.length;i++)
			{
				var $x:int = _walkableChangeList[i][0];
				var $y:int = _walkableChangeList[i][1];
				if($x >= _mapGrid.startX && $x < _mapGrid.numCols + _mapGrid.startX &&
					$y >= _mapGrid.startY && $y < _mapGrid.numRows + _mapGrid.startY)
				{
					_mapGrid.setWalkable($x - _mapGrid.startX ,$y - _mapGrid.startY,getWalkable($x,$y));
				}
			}
		}
		
		
		/**
		 * 将位置改变的对象重新添加到map中,
		 */
		private function addChangeObjectToMap():void
		{
			for(var item:Object in _changeObjectDic)
			{
				exeRemoveIsoObject(item as IsoObject);
				exeAddIsoObject(item as IsoObject);
			}
		}
		
		/**
		 * 取得地图中某个格子的描述 
		 */
		private function getMapItem(x:int,z:int,type:String = IsoType.OBJECT,addChange:Boolean = true):IsoMapItem
		{
			if(addChange) addChangeObjectToMap();
			var $dic:Dictionary;
			if(type == IsoType.OBJECT) $dic = _dic;
			else $dic = _floorDic;
			
			if($dic[x] == null) return null;
			return $dic[x][z];
		}
		
		/**
		 * 创建一个mapItem到一个位置
		 */
		private function createMapItem(x:int,z:int,type:String = IsoType.OBJECT):IsoMapItem
		{
			var $dic:Dictionary;
			if(type == IsoType.OBJECT) $dic = _dic;
			else $dic = _floorDic;
			
			if($dic[x] == null) $dic[x] = new Dictionary();
			if($dic[x][z] == null) $dic[x][z] = new IsoMapItem();
			return $dic[x][z];
		}
		
		/**
		 * 取得一个坐标的可通行值
		 */
		public function getWalkable(x:int,z:int):int
		{
			var $mapItemObject:IsoMapItem = getMapItem(x,z,IsoType.OBJECT);
			var $mapItemFloor:IsoMapItem = getMapItem(x,z,IsoType.FLOOR);
			
			if($mapItemObject == null && $mapItemFloor == null)
			{
				return 0;
			}else if($mapItemObject == null){
				return $mapItemFloor.walkable;
			}else if($mapItemFloor == null){
				return $mapItemObject.walkable;
			}else if($mapItemObject.walkable == 0 || $mapItemFloor.walkable == 0){
				return 0;
			}else{
				return Math.max($mapItemObject.walkable,$mapItemFloor.walkable);
			}
		}
		
		
		/**
		 * 设置某一个格子的通行状态 
		 * 
		 */
		public function setWalkable(x:int,z:int,value:int):void
		{
			var $mapItemObject:IsoMapItem = getMapItem(x,z,IsoType.OBJECT);
			if($mapItemObject == null) $mapItemObject = createMapItem(x,z,IsoType.OBJECT);
			$mapItemObject.setWalkable(value);
			
			_walkableChangeList.push([x,z]);
		}

		/**
		 * 已经变化的物件列表
		 */
		darwin function get changeObjectDic():Dictionary
		{
			return _changeObjectDic;
		}

		/**
		 *	已变化的物件的数量 
		 */
		darwin function get changeObjectCount():int
		{
			return _changeObjectCount;
		}
		
		
		
//     被废弃方法		
//		/**
//		 * 判断一个物件是否在某个点之下
//		 */
//		internal function containsPoint(isoObject:IsoObject,x:int,z:int):Boolean
//		{
//			var $p:IsoPosition = isoObject.isoPosition;
//			var $mp:IsoPosition = isoObject.maxIsoPosition;
//			if(x>=$p.x && x<=$mp.x && z>=$p.z && z<=$mp.z)
//			{
//				return true;
//			}else{
//				return false;
//			}
//		}
//		
//		/**
//		 * 判断一个物件是否在某个区域之下
//		 */
//		internal function contains(isoObject:IsoObject,startX:int,startZ:int,endX:int,endZ:int):Boolean
//		{
//			var $p:IsoPosition = isoObject.isoPosition;
//			var $mp:IsoPosition = isoObject.maxIsoPosition;
//			
//			if((($p.x <= startX && $p.x >= endX) || ($p.z <= startZ && $p.z >= endZ))
//				&&
//				(($mp.x <= startX && $mp.x >= endX) || ($mp.z <= startZ && $mp.z >= endZ)))
//			{
//				return true;
//			}else{
//				return false;
//			}
//		}
//		
		
	}
}